//ACV_Init_Common.sqf
//#define __ACV_Trace

#include "ACV_constantes.h"
[] execVM "tmf\core\modules\r3f_acv\Scripts\ACV_functions_dlg.sqf";
call compile preprocessFile "tmf\core\modules\r3f_acv\functions\fnct_lib.sqf";

/** Tableau pour stocker les unités/ Groupes créés **/
ACV_Unit_Stock = Server getVariable "ACV_Unit_Stock";
if (isnil "ACV_Unit_Stock") then {
	ACV_Unit_Stock = [];
	ACV_Unit_Number = 1;
	Server setVariable ["ACV_Unit_Stock",ACV_Unit_Stock,true];
	Server setVariable ["ACV_Unit_Number",ACV_Unit_Number,true];
} else {
	ACV_Unit_Number = Server getVariable "ACV_Unit_Number";
};
/** Tableau pour stocker les objects créés **/
ACV_Object_Stock = Server getVariable "ACV_Object_Stock";
if (isnil "ACV_Object_Stock") then {
	ACV_Object_Stock = [];
	ACV_Object_Number = 1;
	Server setVariable ["ACV_Object_Stock",ACV_Object_Stock,true];
	Server setVariable ["ACV_Object_Number",ACV_Object_Number,true];
} else {
	ACV_Object_Number = Server getVariable "ACV_Object_Number";
};
/**-------------------------------------------------
Ranger dans le tableau des stocks de groups ou d'objet l'entité fournie
function ACV_FNCT_PutInStock()
@param int Type de l'unité/group/object à ranger
@param object L'entité à ranger (unité/group/object)
@return void
-------------------------------------------------**/
ACV_FNCT_PutInStock = {
	private ["_type","_entite","_pname","_owner","_varname","_name"];
	_type = _this select 0;
	_entite = _this select 1;
	_pname = _this select 2;
	_owner = _this select 3;
	// diag_log Format["%1: %2","ACV_FNCT_PutInStock", _this];
	if ((_type == ACV_NET_MAKESIMPLEOBJECT) || (_type == ACV_NET_MAKEAMMOBOX)) then {
		_varname = format ["OBJ%1", ACV_Object_Number];
		_name = format ["%1 %2", _varname, _pname];
		_entite Call Compile Format ["%1=_this; PublicVariable ""%1""",_varname];
		_entite setvariable ["Name", _name, true];
		_entite setvariable ["VarName", _varname, true];
		_entite setvariable ["ACVType", "OBJ", true];
		ACV_Object_Stock = Server getVariable "ACV_Object_Stock";
		ACV_Object_Number = Server getVariable "ACV_Object_Number";
		// diag_log Format["%1: %2","ACV_FNCT_PutInStock", [_varname,_name,_entite,ACV_Object_Stock,ACV_Object_Number]];
		ACV_Object_Stock set [count ACV_Object_Stock, _entite];
		ACV_Object_Number = ACV_Object_Number + 1;
		Server setVariable ["ACV_Object_Stock", ACV_Object_Stock, true];
		Server setVariable ["ACV_Object_Number", ACV_Object_Number, true];
		if (!IS_Client) then {
			ACV_NET_RefreshListObjects = [_varname, 0, _owner];
			publicVariable "ACV_NET_RefreshListObjects";
		} else {
			[_varname, 0, _owner] call ACV_FNCT_RefreshListObjects;
		};
	} else {
		ACV_Unit_Stock = Server getVariable "ACV_Unit_Stock";
		ACV_Unit_Number = Server getVariable "ACV_Unit_Number";
		_varname = _entite getVariable "VarName";
		_name = _entite getVariable "Name";
		// We check if the entity already exists in the stock.
		if (_entite in ACV_Unit_Stock) then {
			diag_log Format["%1: %2 %3","ACV_FNCT_PutInStock","Entity already exists", [_varname,_name,_entite,ACV_Unit_Number,ACV_Unit_Stock]];
		} else {
			_varname = format ["GRP%1", ACV_Unit_Number];
			_name = format ["%1 %2", _varname, _pname];
			_entite Call Compile Format ["%1=_this; PublicVariable ""%1""",_varname];
			_entite setvariable ["Name", _name, true];
			_entite setvariable ["VarName", _varname, true];
			_entite setvariable ["ACVType", "GRP", true];
			ACV_Unit_Stock set [count ACV_Unit_Stock, _entite];
			ACV_Unit_Number = ACV_Unit_Number + 1;
			Server setVariable ["ACV_Unit_Stock", ACV_Unit_Stock,true];
			Server setVariable ["ACV_Unit_Number", ACV_Unit_Number,true];
		};
		if (!IS_Client) then {
			ACV_NET_RefreshListUnits = [_varname, 0, _owner];
			publicVariable "ACV_NET_RefreshListUnits";
			//diag_log format["SERVER-> SendTo Client %1/%2", _varname, _owner];
		} else {
			[[_varname, 0, _owner]] call ACV_FNCT_RefreshListunits;
		};
	};
};
/**-------------------------------------------------
Creer un group
function ACV_FNCT_MakeGroup
@param string side
@return group le group ou gprull si echec
-------------------------------------------------**/
ACV_FNCT_MakeGroup = {
	private ["_side","_group"];
	_side = _this select 0;
	try {
		_group = grpNull;
		if ((_side=="EAST") || (_side == "East")) then {
			_group = createGroup east;
		};
		if ((_side=="WEST") || (_side == "West")) then {
			_group = createGroup west;
		};
		if ((_side=="GUER") || (_side=="Guerrila")) then {
			_group = createGroup resistance;
		};
		if ((_side=="CIV") || (_side == "Civilian")) then {
			_group = createGroup civilian;
		};
		if (_group == grpNull) then {
			call compile format["_group = createGroup %1;",_side];
		};
	} catch {
		_group = grpNull;
	};
	_group;
};
/**-------------------------------------------------
Creer un object simple
function ACV_FNCT_MakeObjects
@param array Tableau de parametres variable
	ACV_NET_PARAM_TYPE (Usage interne)
	ACV_NET_PARAM_CLASS (nom de la classe de l'objet à créer)
	ACV_NET_PARAM_POS (La position du groupe à créer)
	ACV_NET_PARAM_DIR	(Direction à donner au véhicule)
	ACV_NET_PARAM_OWNER (Le nom de celui qui commande la creation)
@return objects if success ou objNull if not
-------------------------------------------------**/
ACV_FNCT_MakeObjects = {
	private ["_params","_type","_class","_pos","_dir","_displayname","_owner","_type_obj","_objs","_obj","_code","_x","_special"];
	try {
		_params = _this select 0;
		_type = _params select ACV_NET_PARAM_TYPE;
		_class = _params select ACV_NET_PARAM_CLASS;
		_pos = _params select ACV_NET_PARAM_POS;
		_dir = _params select ACV_NET_PARAM_DIR;
		_displayname = _params select ACV_NET_PARAM_DISPLAYNAME;
		_owner = _params select ACV_NET_PARAM_OWNER;
		_type_obj = _params select ACV_NET_PARAM_OTHER;
		_special = "";
		if (count _params > ACV_NET_PARAM_SPECIAL) then { _special = _params select ACV_NET_PARAM_SPECIAL; };
		diag_log format["*** ACV MAKE OBJECT *** %1",_this];
		if (_type_obj == "Compositions") then {
			_objs = [_pos, _dir, _class] call (compile (preprocessFileLineNumbers "ca\modules\dyno\data\scripts\objectMapper.sqf"));
			{
				[_type, _x, getText(configfile >> "cfgVehicles" >> typeOf (_x) >> "displayname"), _owner] call ACV_FNCT_PutInStock;
			} foreach _objs;
		} else {
			//_obj = _class createVehicle _pos;
			If ((_pos select 2) < 0) then {_pos set [2,0];};
			_obj = createVehicle [_class,_pos,[],0,_special];
			_obj setPos _pos;
			_obj setDir _dir;
			[_type, _obj, _displayname, _owner] call ACV_FNCT_PutInStock;
		};
		[format [localize "STR_MSG_CREATEDBY",_displayname,_owner]] call ACV_FNCT_BroadcastMessage;
		if (_class isKindOf "AIR") then {
			// Done in the template on the player themselves
			// _code = compile format ["%1 addAction [""HALO"" call R3F_FNCT_Blue,""client\halo.sqf"",[],1,false,false,"""",""((getPosATL _target) select 2) > 200""];",(_obj getVariable "VarName")];
			// [ACV_BROADCAST_TO_ALL,_code,_code] call ACV_FNCT_BroadcastCode;
		};
	} catch {
		_obj = objNull;
	};
	_obj;
};
/**-------------------------------------------------
Créer une unité simple
function ACV_FNCT_MakeUnits()
@param array tableau de parametres
Le tableau de parametres contient:
	ACV_NET_PARAM_TYPE (Usage interne)
	ACV_NET_PARAM_CLASS (nom de la classe de l'objet à créer)
	ACV_NET_PARAM_POS (La position du groupe à créer)
	ACV_NET_PARAM_DIR	(Direction à donner au véhicule)
	ACV_NET_PARAM_OWNER (Le nom de celui qui commande la creation)
	ACV_NET_PARAM_SIDE (nom de la side à laquelle appartient le vehicule)
	ACV_NET_PARAM_DISPLAYNAME (Le nom 'en clair' du véhicule à créer)
	ACV_NET_PARAM_SKILL (Le skill des membres du groupe)
	ACV_NET_PARAM_RANK (Le grade de l'unité)

@return Group Le group créé ou grpNull en cas d'échec
-------------------------------------------------**/
ACV_FNCT_MakeUnits = {
	private ["_params","_type","_class","_pos","_dir","_displayname","_owner","_side","_skill","_rank","_group","_obj","_arr_wp","_special"];
	try {
		_params = _this select 0;
		_type = _params select ACV_NET_PARAM_TYPE;
		_class = _params select ACV_NET_PARAM_CLASS;
		_pos = _params select ACV_NET_PARAM_POS;
		_dir = _params select ACV_NET_PARAM_DIR;
		_displayname = _params select ACV_NET_PARAM_DISPLAYNAME;
		_owner = _params select ACV_NET_PARAM_OWNER;
		_side = _params select ACV_NET_PARAM_SIDE;
		_skill = _params select ACV_NET_PARAM_SKILL;
		_rank = _params select ACV_NET_PARAM_RANK;
		diag_log format["*** ACV MAKE UNITS *** %1",_this];
		if (typeName _side != "STRING") then {
			_group = _side;
			_side= switch (side _side) do {
				case west: {"WEST"};
				case east: {"EAST"};
				case resistance: {"GUER"};
				default {"CIV"};
			};
		} else {
			_group = [_side] call ACV_FNCT_MakeGroup;
		};
		_special = "NONE";
		if (count _params > ACV_NET_PARAM_SPECIAL) then { _special = _params select ACV_NET_PARAM_SPECIAL; };
		if (typeName _class == "STRING") then {_class = [_class];};
		{
			_obj = _group createUnit [_x, _pos, [], (count _class - 1), _special];
			_obj setSkill _skill;
			_obj setUnitRank _rank;
			_obj setPos [_pos select 0, _pos select 1, 0];
			_obj setDir _dir;
		} foreach _class;
		_arr_wp = waypoints _group;
		(_arr_wp select 0) setWPPos _pos;
		[_type, _group, _displayname, _owner] call ACV_FNCT_PutInStock;
		[format[localize "STR_MSG_CREATEDBY", _displayname, _owner]] call ACV_FNCT_BroadcastMessage;
	} catch {
		_group = grpNull;
	};
	_group;
};
/**-------------------------------------------------
Créer un véhicule avec son équipage en vol ou non
function ACV_FNCT_MakeVehicles()
@param array tableau de parametres
Le tableau de parametres contient:
	ACV_NET_PARAM_TYPE (Usage interne)
	ACV_NET_PARAM_CLASS (nom de la classe de l'objet à créer)
	ACV_NET_PARAM_POS (La position du groupe à créer)
	ACV_NET_PARAM_DIR	(Direction à donner au véhicule)
	ACV_NET_PARAM_OWNER (Le nom de celui qui commande la creation)
	ACV_NET_PARAM_SIDE (nom de la side à laquelle appartient le vehicule)
	ACV_NET_PARAM_DISPLAYNAME (Le nom 'en clair' du véhicule à créer)
	ACV_NET_PARAM_SKILL (Le skill des membres du groupe)
	ACV_NET_PARAM_FLYING (si le véhicule doit être créér en vol ou pas)
@return Group Le group créé ou grpNull en cas d'échec
-------------------------------------------------**/
ACV_FNCT_MakeVehicles = {
	private ["_params","_type","_class","_pos","_dir","_displayname","_owner","_side","_skill",
	"_rank","_en_vol","_sim","_group","_array","_vehicle","_x","_arr_wp"];
	try {
		// diag_log format["ACV_FNCT_MakeVehicles -> Recept : %1", _this];
		_params = _this select 0;
		_type = _params select ACV_NET_PARAM_TYPE;
		_class = _params select ACV_NET_PARAM_CLASS;
		_pos = _params select ACV_NET_PARAM_POS;
		_dir = _params select ACV_NET_PARAM_DIR;
		_displayname = _params select ACV_NET_PARAM_DISPLAYNAME;
		_owner = _params select ACV_NET_PARAM_OWNER;
		_side = _params select ACV_NET_PARAM_SIDE;
		_skill = _params select ACV_NET_PARAM_SKILL;
		_rank = _params select ACV_NET_PARAM_RANK;
		_en_vol = _params select ACV_NET_PARAM_FLYING;
		if (typeName _side != "STRING") then {
			_group = _side;
			_side= switch (side _side) do {
				case west: {"WEST"};
				case east: {"EAST"};
				case resistance: {"GUER"};
				default {"CIV"};
			};
		} else {
			_group = [_side] call ACV_FNCT_MakeGroup;
		};
		_sim = getText (configFile >> "CfgVehicles" >> _class >> "simulation");
		diag_log format["*** ACV MAKE VEHICLE *** %1",_params + [_sim]];
		if (_en_vol == 1) then {
			if (_sim == "helicopter") then {
				_pos set [2,(random 100) + 100];
			};
			if (_sim == "airplane") then {
				_pos set [2,(random 100) + 200];
			};
			if (_sim != "helicopter" && _sim != "airplane") then {
				_pos set [2,0];
			};
		} else {
			_pos set [2,0];
		};
		diag_log format["*** ACV MAKE VEHICLE *** %1",[_pos,_dir,_class,_group]];
		_array = [_pos,_dir,_class,_group] call BIS_fnc_spawnVehicle;
		diag_log format["*** ACV MAKE VEHICLE *** %1",_array];
		_vehicle = _array select 0;
		{
			_x setskill _skill;
		} foreach units _group;
		if (_class isKindOf "AIR") then {
			if (_en_vol == 1) then {
				if (_sim == "helicopter") then {
					_vehicle setVelocity [50 * (sin _dir), 50 * (cos _dir), 100];
				};
				if (_sim == "airplane") then {
					_vehicle setVelocity [150 * (sin _dir), 150 * (cos _dir), 100];
				};
			} else {
				_vehicle setpos [(getPos _vehicle) select 0, (getPos _vehicle) select 1, 0];
				_vehicle setVelocity [0 * (sin _dir), 0 * (cos _dir), 0];
				(driver _vehicle) action ["engineOff", _vehicle];
			};
		};
		_arr_wp = waypoints _group;
		(_arr_wp select 0) setWPPos _pos;
		[_type, _group, _displayname, _owner] call ACV_FNCT_PutInStock;
		[ format[localize "STR_MSG_CREATEDBY",_displayname, _owner]] call ACV_FNCT_BroadcastMessage;
	} catch {
		_group = grpNull;
	};
	_group;
};
/**-------------------------------------------------
Créer un groupe au complet avec ou sans véhicles
Le groupe à créer fait partie de la class CfgGroups
function ACV_FNCT_MakeGroups()
@param array tableau de parametres
Le tableau de parametres contient:
	ACV_NET_PARAM_TYPE (Usage interne)
	ACV_NET_PARAM_POS (La position du groupe à créer)
	ACV_NET_PARAM_OWNER (Le nom de celui qui commande la creation)
	ACV_NET_PARAM_DISPLAYNAME (Le nom 'en clair' du groupe à créer)
	ACV_NET_PARAM_SKILL (Le skill des membres du groupe)
	ACV_NET_PARAM_OTHER (Tableau de données sur le groupe à creer)
			SIDE		ex : west
			FACTION		ex : BIS_US
			TYPE		ex : Armored
			CLASSNAME 	ex : US_MGSPlatoon
@return Group Le group créé ou grpNull en cas d'échec
-------------------------------------------------**/
ACV_FNCT_MakeGroups = {
	private ["_params","_type","_pos","_dir","_displayname","_owner","_side","_str_side","_skill","_arr","_group","_x","_arr_wp"];
	try {
		// diag_log format["ACV_FNCT_MakeGroups -> Recept : %1", _this];
		_params = _this select 0;
		_type = _params select ACV_NET_PARAM_TYPE;
		_pos = _params select ACV_NET_PARAM_POS;
		_dir = _params select ACV_NET_PARAM_DIR;
		_displayname = _params select ACV_NET_PARAM_DISPLAYNAME;
		_owner = _params select ACV_NET_PARAM_OWNER;
		_str_side = _params select ACV_NET_PARAM_SIDE;
		_skill = _params select ACV_NET_PARAM_SKILL;
		_arr = _params select ACV_NET_PARAM_OTHER;
		// diag_log format["Server -> Recept : %1", _params];
		diag_log format["*** ACV MAKE GROUP *** %1",_params];
		if (_displayname != "") then {
			_side = if (_str_side == "Guerrila") then {resistance;} else {call compile format ["%1",_str_side];};
			_group = grpNull;
			if (count _arr <= 4 || {(_arr select 4) <= 0}) then {
				_group = [_pos,_side,(configFile >> "CfgGroups" >> (_arr select 0) >> (_arr select 1) >> (_arr select 2) >> (_arr select 3)),[],[],[],[],[],_dir] call BIS_fnc_spawnGroup;
				//diag_log format["*** ACV MAKE CONFIG GROUP *** %1",[_arr,_side]];
			} else {
				_group = [_pos,_side,(missionConfigFile >> "ACV_CustomGroups" >> (_arr select 0) >> (_arr select 1) >> (_arr select 2) >> (_arr select 3)),[],[],[],[],[],_dir] call BIS_fnc_spawnGroup;
				//diag_log format["*** ACV MAKE CUSTOM GROUP *** %1",[_arr,_side]];
			};
			_group setFormDir _dir;
			{	_x setskill _skill;
			} foreach units _group;
			_arr_wp = waypoints _group;
			(_arr_wp select 0) setWPPos _pos;
			[_type, _group, _displayname, _owner] call ACV_FNCT_PutInStock;
			[format[localize "STR_MSG_CREATEDBY",_displayname,_owner]] call ACV_FNCT_BroadcastMessage;

		} else {
			[format[localize "STR_MSG_GROUPNOTCREATED",_owner]] call ACV_FNCT_BroadcastMessage;
		};
	} catch {
		_group = grpNull;
	};
	_group;
};
ACV_FNCT_DeleteObject = {
	private ["_params","_obj","_owner","_displayname","_idx","_forIndex","_x","_varname"];
	_params = _this select 0;
	_obj = _params select ACV_NET_PARAM_CLASS;
	_owner = _params select ACV_NET_PARAM_OWNER;
	_displayname = _params select ACV_NET_PARAM_DISPLAYNAME;
	_idx = -1;
	diag_log format["*** ACV DELETE OBJECT *** %1",_params];
	_forIndex = 0;
	{
		if (_x == _obj) exitWith {_idx = _forIndex;};
		_forIndex = _forIndex + 1;
	} foreach ACV_Object_Stock;
	if (_idx > -1) then{
		ACV_Object_Stock set [_idx,-1];
		ACV_Object_Stock = ACV_Object_Stock - [-1];
		Server setVariable ["ACV_Object_Stock", ACV_Object_Stock, true];
		deleteVehicle _obj;
		if (!IS_Client) then {
			ACV_NET_RefreshListObjects = [_varname,1,_owner];
			publicVariable "ACV_NET_RefreshListObjects";
		} else {
			[[_varname,1,_owner]] call ACV_FNCT_RefreshListObjects;
		};
	};
};
ACV_FNCT_DeleteUnit = {
	private ["_params","_grp","_owner","_displayname","_varname","_idx","_forIndex","_x"];
	_params = _this select 0;
	_grp = _params select ACV_NET_PARAM_CLASS;
	_owner = _params select ACV_NET_PARAM_OWNER;
	_displayname = _params select ACV_NET_PARAM_DISPLAYNAME;
	_varname = _grp getVariable "VarName";
	_idx = -1;
	diag_log format["*** ACV DELETE UNIT *** %1",_params];
	_forIndex = 0;
	{	if (_x == _grp) exitWith{ _idx = _forIndex;};
		_forIndex = _forIndex + 1;
	} foreach ACV_Unit_Stock;
	if (_idx > -1) then{
		ACV_Unit_Stock set [_idx, -1];
		ACV_Unit_Stock = ACV_Unit_Stock - [-1];
		Server setVariable ["ACV_Unit_Stock", ACV_Unit_Stock, true];
		{
			if (vehicle _x != _x) then {
				deleteVehicle (vehicle _x);
			};
			deleteVehicle _x;
		} foreach units _grp;
		deleteGroup _grp;
		if (!IS_Client) then {
			ACV_NET_RefreshListUnits = [_varname,1,_owner];
			publicVariable "ACV_NET_RefreshListUnits";
		} else {
			[[_varname,1,_owner]] call ACV_FNCT_RefreshListUnits;
		};
		[format[localize "STR_MSG_ERASEDBY",_displayname,_owner]] call ACV_FNCT_BroadcastMessage;
	};
};
ACV_FNCT_GRANT_ACCESS = {
	private ["_params"];
	diag_log Format["ACV_FNCT_GRANT_ACCESS: %1", _this];
};